From c9206131930d6b0ae4df9c1798ce734f263ff042 Mon Sep 17 00:00:00 2001 From: Liigo Zhuang Date: Sun, 14 Dec 2014 21:34:33 +0800 Subject: [PATCH] print non-fatal errors to stdout instead of stderr e.g. docopt treat version as non-fatal error Fixes #1033 --- src/cargo/core/shell.rs | 4 ++++ src/cargo/lib.rs | 41 ++++++++++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs index 7a83ac491..109652555 100644 --- a/src/cargo/core/shell.rs +++ b/src/cargo/core/shell.rs @@ -77,6 +77,10 @@ impl MultiShell { pub fn set_verbose(&mut self, verbose: bool) { self.verbose = verbose; } + + pub fn get_verbose(&self) -> bool { + self.verbose + } } pub type ShellCallback<'a> = |&mut Shell|:'a -> IoResult<()>; diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index 2dd20824f..8943c3e5d 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -32,7 +32,7 @@ use serialize::{Decoder, Encoder, Decodable, Encodable, json}; use docopt::Docopt; use core::{Shell, MultiShell, ShellConfig}; -use term::color::{BLACK}; +use term::color::{BLACK, RED}; pub use util::{CargoError, CliError, CliResult, human}; @@ -178,35 +178,54 @@ pub fn shell(verbose: bool) -> MultiShell { MultiShell::new(out, err, verbose) } + +// `output` print variant error strings to either stderr or stdout. +// For fatal errors, print to stderr; +// and for others, e.g. docopt version info, print to stdout. +fn output(caption: Option, detail: Option, + shell: &mut MultiShell, fatal: bool) { + let std_shell = if fatal {shell.err()} else {shell.out()}; + if let Some(caption) = caption { + let color = if fatal {RED} else {BLACK}; + let _ = std_shell.say(caption, color); + } + if let Some(detail) = detail { + let _ = std_shell.say(detail, BLACK); // always black + } +} + pub fn handle_error(err: CliError, shell: &mut MultiShell) { log!(4, "handle_error; err={}", err); let CliError { error, exit_code, unknown } = err; + let verbose = shell.get_verbose(); + let fatal = exit_code == 1; // exit_code == 0 is non-fatal error if unknown { - let _ = shell.error("An unknown error occurred"); + output(Some("An unknown error occurred".to_string()), None, shell, fatal); } else if error.to_string().len() > 0 { - let _ = shell.error(error.to_string()); + output(Some(error.to_string()), None, shell, fatal); } if error.cause().is_some() || unknown { - let _ = shell.concise(|shell| { - shell.err().say("\nTo learn more, run the command again with --verbose.", BLACK) - }); + if !verbose { + output(None, + Some("\nTo learn more, run the command again with --verbose.".to_string()), + shell, fatal); + } } - let _ = shell.verbose(|shell| { + if verbose { if unknown { - let _ = shell.error(error.to_string()); + output(Some(error.to_string()), None, shell, fatal); } if let Some(detail) = error.detail() { - let _ = shell.err().say(format!("{}", detail), BLACK); + output(None, Some(detail), shell, fatal); } if let Some(err) = error.cause() { let _ = handle_cause(err, shell); } - Ok(()) - }); + } std::os::set_exit_status(exit_code as int); } -- 2.30.2